package com.hzit.cart.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.hzit.cart.dto.ItemDTO;
import com.hzit.cart.interceptor.LoginInterceptor;
import com.hzit.cart.service.CartService;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.uuid.UUID;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.system.api.RemoteManagerService;
import com.ruoyi.system.api.domain.Item;
import com.ruoyi.system.api.factory.RemoteManagerFallbackFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Service
public class CartServiceImpl implements CartService {

	@Autowired
	private RemoteManagerService managerService;
	@Autowired
	private StringRedisTemplate redisTemplate;
	/**
	 * 1. 添加购物车到redis中
	 * 1.1 存放到redsi中的购物车数据的数据结构如何?
	 *     首先，可以选择使用hash存放，其中的：
	 *     ① 大key：我们可以定义成：hzit-cart:登录名
	 *     ② 小key：当前添加的商品的id
	 *     ③ 当前要添加的商品
	 * 1.2 具体落实：
	 *     ① 判断在redis中是否有此商品，如果有，就修改数量及库存
	 *     ② 如果没有就添加到redis中
	 */

	@Override
	public void addCart(Long itemId, Integer num) {
		//1. 根据商品id查询出商品
		R<Item> r = managerService.findItemById(itemId);
		Item item = r.getData();
		//2. 判断在redis中是否有此商品
		//2.1 得到登录名
		String name = LoginInterceptor.local.get();
		//2.2 判断是否有此key
		Boolean hasKey = redisTemplate.opsForHash().hasKey(Constants.CART_PREFIX + name, itemId + "");
		//2.3 如果有此key，就修改商品
		ItemDTO dto = null;
		if(hasKey){
			//2.3.1 获取到存放到redis中的商品
			String itemStr = (String) redisTemplate.opsForHash().get(Constants.CART_PREFIX + name, itemId + "");
			dto = JSON.parseObject(itemStr, ItemDTO.class);
			//2.3.2 修改购买数量
			dto.setBuyNum(dto.getBuyNum() + num);
			//2.3.3 修改库存量
			dto.setNum(dto.getNum() - num);
		}else{
			//2.4 没有此key，就添加到redis中
			dto = new ItemDTO();
			BeanUtil.copyProperties(item,dto,true);
			dto.setBuyNum(num);                 // 修改购买数量
			dto.setNum(dto.getNum() - num);     // 修改库存量
		}
		// 最后统一保存到redis中
		RedisOperations<String, String> operations = (RedisOperations<String, String>) redisTemplate.opsForHash().getOperations();
		// 到期时间设置10h
		operations.expire(Constants.CART_PREFIX + name,30, TimeUnit.DAYS);
		// 添加数据到redis中
		operations.opsForHash().put(Constants.CART_PREFIX + name, itemId + "",JSON.toJSONString(dto));

	}

	//2. 将redis中所有的数据进行整合成以商家名称为分类的数据
	@Override
	public Map<String, List<ItemDTO>> findItemsFromRedis() {
		//2.0 获取登录名
		String name = LoginInterceptor.local.get();
		//2.1 从redis中将数据查询出来
		List<Object> values = redisTemplate.opsForHash().values(Constants.CART_PREFIX + name);
		//2.2 将List<Object>列表转换为List<ItemDTO>
		List<ItemDTO> collect = values.stream().map(m -> {
			ItemDTO dto = JSON.parseObject(m.toString(), ItemDTO.class);
			return dto;
		}).collect(Collectors.toList());
		//2.3 对List<ItemDTO>进行聚合查询，聚合时的key为: 商家的名字value为：此商家下的商品列表
		Map<String, List<ItemDTO>> cartList = collect.stream().collect(Collectors.groupingBy(gb -> gb.getSeller()));

		return cartList;
	}

	//3. 根据商品id查询出商品
	@Override
	public ItemDTO findItemByItemId(Long itemId, Integer num) {
		//3.1 根据商品id查询出商品
		String itemStr = (String) redisTemplate.opsForHash().get(Constants.CART_PREFIX + LoginInterceptor.local.get(), itemId + "");
		//3.2  转换为ItemDTO对象
		ItemDTO dto = JSON.parseObject(itemStr, ItemDTO.class);
		//3.3  设置购买数量
		dto.setBuyNum(num);
		return dto;
	}

	//4. 生成一个随机的token值
	@Override
	public String createToken() {
		//4.1 生成一个随机的uuid字符串
		String token = UUID.randomUUID().toString();
		//4.2 将其保存到redis中
		redisTemplate.opsForValue().set(Constants.ORDER_TOKEN_PREFIX + LoginInterceptor.local.get(),token,10,TimeUnit.DAYS);
		//4.3 返回token
		return token;
	}
}

